package drazing;

import java.awt.Color;

/**
 * Clase que define atributos y métodos para tratar un coche
 * @author xcubo
 */
public class Car extends Molde
{
        //CONSTANTES
        public static final int LeftFrontTire = 0;
        public static final int RightFrontTire = 1;
        public static final int LeftBackTire = 2;
        public static final int RightBackTire = 3;
        public static final int FrontWing = 10;
        public static final int BackWing = 11;

        //Parámetros de conducción
        private boolean ok;
        private double speed;
        //private int direccion;
        private int orientacion;
        private double fuel;
        private double tire_life;
        private double tire_wear;

        //Parámetros de pintado
        private Color pri, sec, ter;

        //Constantes Técnicas del Coche
        private final double poten;
        private final double freno;
        private final double carga;
        private double vmax;      

        //Partes
        private Tire del_izq;
        private Tire del_der;
        private Tire tra_izq;
        private Tire tra_der;
        private boolean del_ala, tra_ala;
        private int cont_giro;

        //Variables de carrera
        private Tiempo tabla[];
        /**
         * Inicia un coche con su posición inicial y los settings correspondientes
         * @param x Coordenada x
         * @param y Coordenada y
         * @param setup Settings del coche
         */
        public Car(int x, int y, Settings setup)
        {
            super(x,y);                                 // Constructor de Imagen
            ok = true;
                                                        // Cargamos Características Técnicas del coche
            poten = ((setup.getPot())*0.735) - (setup.getGear()*50);            //Potencia base a KW menos desarrollo
            System.out.println("Pot: "+poten);
            freno = setup.getBrak();
            carga = (setup.getAero())+0.5;              // Aerodinamica + peso
            fuel = setup.getFuel();
            vmax = Math.pow(poten*1000/(0.613*carga),(1.0/3.0)) + (setup.getGear() * 5);    // En m/s
            System.out.println("vmax: "+vmax);
            if (setup.getTire())
                tire_wear = 0.00001;
            else
                tire_wear = 0.0001;

            tire_life = 1.0;

            if(setup.getTeam().equals("Ferrari"))
            {
                pri = Color.RED;
                sec = Color.RED;
                ter = Color.WHITE;
            }
            else if (setup.getTeam().equals("McLaren"))
            {
                pri = Color.GRAY;
                sec = Color.RED;
                ter = Color.RED;
            }
            else if (setup.getTeam().equals("Renault"))
            {
                pri = new Color(47,145,255);
                sec = new Color(255,252,0);
                ter = new Color(255,252,0);
            }

            speed = 0;                          // Parámetros Actuales
            orientacion = 16;

            tabla = new Tiempo[100];

            del_izq = new Tire();               //Piezas
            del_der = new Tire();
            tra_izq = new Tire();
            tra_der = new Tire();
            del_ala = true;
            tra_ala = true;

            cont_giro = 0;
        }

        public double getSpeed()
        {
            return speed;
        }
        public void setSpeed(double sp)
        {
            speed = sp;
        }
        public double getFuel()
        {
            return fuel;
        }
        public int getOrientacion()
        {
            return orientacion;
        }

        public void setOrientacion(int or)
        {
            orientacion = or;
        }
        public double getCarga()
        {
            return carga;
        }
        public double getMaxSpeed()
        {
            return vmax;
        }

        /**
         * Acelera el coche
         * @param accel_fact Factor de aceleración
         */
        public void acelerar(double accel_fact)
        {
            double acele;
            double peso = carga + fuel;                                       // La suma es el peso (del combustible por ejemplo)

            if (ok)
            {
                //System.out.println("Speed: "+speed+" , "+"Max speed: "+max_speed+" , "+"Carga: "+carga+" , "+"Max throttle: "+max_throt+" , "+"Accel: "+acele);
                if (speed < 2)
                    acele = 2;                              // Aceleracion en parado
                else if(speed <= vmax)
                {
                    acele = (poten/(speed*peso));
                    acele = accel_fact * acele;
                }
                else
                {
                    acele = 0;
                    decelerar(1);
                }
                speed += acele;
                if (fuel <= 0 || tire_life <= 0)
                    ok = false;
                //System.out.println("Aceleraci: "+acele);
                //System.out.println("Velocidad: "+speed);

                //System.out.println("--------------------");
            }
        }

        /**
         * Frena el coche
         * @param brake_fact Factor de freno
         */
        public void frenar(double brake_fact)
        {
            double peso = (carga*speed) + fuel;
            double fre = brake_fact*(freno+peso);
            /*System.out.println("Speed: "+speed);
            System.out.println("Brake: "+fre);*/
            if (speed > 0)
                speed -= fre;
            else
                speed = 0;
            if (brake_fact > 0.3)
            {
                desgastar(0.0001);
            }
        }
        public void decelerar(double time)
        {
            frenar(0.1*time);
        }

        /**
         * Gira a la izquierda
         * @return Exito o no
         */
        public boolean turn_left(double time)
        {
            int future;
            double carga_efectiva = carga*15;

            if (orientacion <= -31)                                            // Precalculamos al cont_giro de giro
                future = 32;
            else
                future = orientacion-1;

            /*System.out.println("Girando a izquierda con");
            System.out.println("Orientacion: "+orientacion);
            System.out.println("Future: "+future);
            System.out.println("Contador de giro: "+Math.abs(cont_giro)+"/"+myCar.speed);
            System.out.println("---------------------");*/

            if(speed > 0)
            {
                if (cont_giro > 0)
                {
                    orientacion = future;
                    cont_giro = 0;
                }
                else if (Math.abs(cont_giro) < speed || cont_giro == 0)           // Si no llega al valor de giro
                {
                    future = orientacion;
                    cont_giro -= (vmax-speed+carga_efectiva)*time*20;
                }
                else
                {
                    cont_giro = 0;
                    orientacion = future;
                }
                //decelerar(0.1);

                return true;
            }
            else
                return false;
        }

        /**
         * Giro a la derecha
         * @return Exito o no
         */
        public boolean turn_right(double time)
        {
            double carga_efectiva = carga*15;
            int future;

            if (orientacion >= 32)                                            // Precalculamos al cont_giro de giro
                future = -31;
            else
                future = orientacion + 1;

            /*System.out.println("Girando a derecha con");
            System.out.println("Orientacion: "+orientacion);
            System.out.println("Future: "+future);
            System.out.println("Contador de giro: "+Math.abs(cont_giro)+"/"+myCar.speed);
            System.out.println("---------------------");*/

            if (speed > 0)
            {
                if (cont_giro < 0)
                {
                    orientacion = future;
                    cont_giro = 0;
                }
                else if (cont_giro < speed || cont_giro == 0)
                {
                    future = orientacion;
                    cont_giro += (vmax-speed+carga_efectiva)*time*20;
                }
                else
                {
                    cont_giro = 0;
                    orientacion = future;
                }
                //decelerar(0.1);
                return true;
            }
            else
                return false;
        }

        /**
         * Desgasta el neumatico
         */
        public void desgastar(double percent)
        {
            double peso = (carga*speed) + fuel;
            double desgaste = tire_wear*peso*percent;
            tire_life = tire_life - desgaste;
        }
        public void vaciar(double mult)
        {
            double cons = (carga+fuel)*0.001;
            fuel = fuel - (cons*mult);
        }
        public boolean isOk()
        {
            return ok;
        }
        public double getTireLife()
        {
            return tire_life;
        }
        public Color getColor(int i)
        {
            assert(i >= 1 && i <= 3);
            if (i == 1)
                return pri;
            else if(i ==2)
                return sec;
            else
                return ter;
        }
        public Tire getTire(int i)
        {
            assert(i >= 0 && i <= 3);
            if (i == 0)
                return del_izq;
            else if(i == 1)
                return del_der;
            else if(i == 2)
                return tra_izq;
            else 
                return tra_der;
        }
        public boolean isWingOK(int i)
        {
            assert(i >= 10 && i <= 11);
            if (i == 10)
                return del_ala;
            else
                return tra_ala;
        }
        public Tiempo getTime(int lap)
        {
            return tabla[lap];
        }
        public void setTime(int lap, Tiempo t)
        {
            tabla[lap] = t;
        }
}